package login

import (
	"appService/src/application"
	"appService/src/application/app/appModels"
	"appService/src/authValid"
	"appService/src/authValid/userAuthType"
	"appService/src/authValid/userMap"
	"appService/src/global"
	"appService/src/libs/crypot"
	"appService/src/libs/token"
	"appService/src/orm"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/net/ghttp"
	"github.com/gogf/gf/util/guid"
	"time"
	"xorm.io/builder"
)

type Login struct {
	application.BaseController
}

//Login 用户登陆
func (this *Login) Login(r *ghttp.Request) {
	req := this.NewRequest(r,nil)
	p := struct {
		Account  string `json:"account"`
		Password string `json:"password"`
		AppCode  string `json:"app_code"`
	}{}
	req.ParamsAnalyse(&p)
	if p.Account == "" {
		req.JsonError("请输入登陆账号")
	}
	if p.Password == "" {
		req.JsonError("请输入登陆密码")
	}
	if p.AppCode == "" {
		req.JsonError("【AppCode】为空")
	} else {
		appCode, _, err := crypot.AESDecrypt(p.AppCode, false)
		if err != nil {
			g.Log().Errorf("用户登录 —> AESDecrypt：解密【AppCode】错误：%v", err)
			req.JsonError("【AppCode】错误")
		}
		if appCode != "" {
			p.AppCode = appCode
		} else {
			g.Log().Errorf("用户登录 —> AESDecrypt：【AppCode】解密结果为空")
			req.JsonError("【AppCode】错误")
		}
	}
	account := new(appModels.Account)
	db := orm.Db.Where(builder.Eq{"account": p.Account})
	ok, err := db.Get(account)
	if err != nil {
		g.Log().Errorf("用户[%v]登陆失败，查询用户账号信息错误：%v", p.Account, err)
		req.JsonError("登陆失败")
	}
	if !ok {
		req.JsonError("账号不存在")
	}
	if account.Password == "" {
		req.JsonError("您没有设置密码，无法登陆，请联系管理员")
	}
	if account.Password != crypot.PassWordEncryption(p.Password) {
		req.JsonError("密码错误")
	}
	user := new(appModels.Users)
	db = orm.Db.Where(builder.Eq{"account_id": account.Id})
	if account.Account != userAuthType.SYSTEM_ADMIN_ACCOUNT {
		db.Where(builder.Eq{"auth_group_id": p.AppCode})
	}
	ok, err = db.Get(user)
	if err != nil {
		g.Log().Errorf("用户[%v]登陆失败，查询用户信息错误：%v", p.Account, err)
		req.JsonError("登陆失败")
	}
	if !ok {
		req.JsonError("您没有登录权限")
	}

	if global.SingleLogin && userMap.Exist(user.Uid) {
		loginUser := userMap.Get(user.Uid)
		if (time.Now().Unix() - loginUser.User.LoginTime.Unix()) < global.SingleLoginTime {
			req.JsonError("该账号已经在另一个地方登陆")
		}
	}
	user.LastLoginTime = user.LoginTime
	user.LoginTime = time.Now()
	user.LoginRand = guid.S()
	user.LastLoginIp = user.LoginIp
	user.LoginIp = req.GetProxyClientIp()
	tokenStr, err := token.NewToken(user.Uid, account.Account, user.LoginRand)
	if err != nil {
		g.Log().Errorf("用户[%v]登陆，生成token失败，错误：%v", p.Account, err)
		req.JsonError("登陆失败")
	}

	//更新登录时间 登录IP
	_, err = orm.Db.Where(builder.Eq{"uid": user.Uid}).Cols("last_login_time,login_time,login_rand,last_login_ip,login_ip").Update(user)
	if err != nil {
		g.Log().Errorf("用户[%v]登陆，更新登陆信息失败，错误：%v", p.Account, err)
		req.JsonError("登陆失败")
	}

	// 判断 账号 是否 有所属部门单位，没有就零时设置为默认的
	if account.Bid == "" || account.Bid == "0" {
		branch, err := req.GetDefaultBranch()
		if err == nil {
			account.Bid = branch.Id
			user.Bid = branch.Id
		} else {
			req.JsonError("登陆失败")
		}
	}
	branch,err:=req.GetDefaultBranch()
	if err != nil {
		g.Log().Errorf("token验证 —> 获取默认部门机构，错误：%v", err)
		req.JsonError("登陆失败")
	}
	//设置登录用户缓存
	req.LoginUser.Account = *account
	req.LoginUser.User = *user
	req.LoginUser.DefaultBranchId = branch.Id
	branchIds := authValid.GetBranchIDs(req.LoginUser,true)
	req.LoginUser.BranchIds = *branchIds
	userMap.Set(req.LoginUser)
	//返回登录信息给用户

	authList := authValid.GetUserAuthList(req.LoginUser, true)
	apiCode := authValid.GetUserAuthCodeList(req.LoginUser)
	req.JsonSuccess("登陆成功", map[string]interface{}{
		"token": tokenStr,
		"user":  req.LoginUser,
		"auth":  authList,
		"api":   apiCode,
		"expires": global.TokenExpiresAt,
	})
}

//OutLogin 退出登录
func (this *Login) OutLogin(r *ghttp.Request) {
	req := this.NewRequest(r,nil)
	if global.SingleLogin {
		if userMap.Exist(req.LoginUser.User.Uid) {
			userMap.Remove(req.LoginUser.User.Uid)
		}
	}
	req.JsonSuccess("已安全退出登录")
}

//GetLoginUserInfo 用户自动登陆 获取用户信息
func (this *Login) GetLoginUserInfo(r *ghttp.Request) {
	req := this.NewRequest(r, nil)
	req.LoginUser.Account.Password = ""
	authList := authValid.GetUserAuthList(req.LoginUser, true)
	apiCode := authValid.GetUserAuthCodeList(req.LoginUser)
	req.JsonSuccessData(map[string]interface{}{
		"user": req.LoginUser,
		"auth": authList,
		"api":  apiCode,
	})
}
